Skip to content

fix(angular-query): track pre-render query promises#10779

Open
raashish1601 wants to merge 3 commits into
TanStack:mainfrom
raashish1601:fix/angular-query-whenstable-preaccess
Open

fix(angular-query): track pre-render query promises#10779
raashish1601 wants to merge 3 commits into
TanStack:mainfrom
raashish1601:fix/angular-query-whenstable-preaccess

Conversation

@raashish1601
Copy link
Copy Markdown
Contributor

@raashish1601 raashish1601 commented May 24, 2026

Fixes #10046.

Summary

  • register Angular PendingTasks for promise-returning query functions as soon as the query function runs
  • preserves synchronous query functions without adding an extra pending task
  • adds a regression for a class-field alias of query.data that is read during render before whenStable()
  • adds a patch changeset for @tanstack/angular-query-experimental

Validation

  • corepack pnpm install --frozen-lockfile
  • corepack pnpm --filter @tanstack/angular-query-experimental exec vitest run src/__tests__/signal-proxy.test.ts src/__tests__/inject-query.test.ts (2 files, 27 tests passed)
  • corepack pnpm exec eslint packages/angular-query-experimental/src/create-base-query.ts packages/angular-query-experimental/src/__tests__/inject-query.test.ts
  • corepack pnpm exec prettier --check .changeset/angular-query-preaccess-whenstable.md packages/angular-query-experimental/src/create-base-query.ts packages/angular-query-experimental/src/__tests__/inject-query.test.ts
  • git diff --check

I also ran corepack pnpm --filter @tanstack/angular-query-experimental exec vitest run; all Angular package tests executed successfully (25 files, 218 tests passed), but the command exited non-zero because this Windows checkout treats repo symlink placeholders like root.eslint.config.js as source and reports TypeCheckError: Declaration or statement expected.

corepack pnpm --filter @tanstack/query-core build is blocked by the same local symlink placeholder issue in packages/query-core/root.tsup.config.js.

Summary by CodeRabbit

  • Bug Fixes

    • Ensure Angular's whenStable() remains pending when query result signals are accessed before a component finishes rendering.
  • Behavior Changes

    • Reset operation now targets and refetches only the queries actually matched by the reset predicate.
  • Tests

    • Added tests for pre-render signal access, never-resolving queries, and reset/refetch behaviors.
  • Chores

    • Added a release changeset.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8b251a47-1b56-459e-8d0b-49ec9ffb3399

📥 Commits

Reviewing files that changed from the base of the PR and between 78263c8 and 9a323f1.

📒 Files selected for processing (2)
  • packages/query-core/src/__tests__/queryClient.test.tsx
  • packages/query-core/src/queryClient.ts

📝 Walkthrough

Walkthrough

Wraps query functions to register Angular pending tasks for thenables, centralizes observer updates into updateState so Angular's whenStable() remains pending when a query data signal is accessed before initial render, adds tests and a changeset, and narrows QueryClient.resetQueries refetches to matched queries only.

Changes

Keep Angular whenStable() pending when query data accessed early

Layer / File(s) Summary
Pending task registration and centralized updateState
packages/angular-query-experimental/src/create-base-query.ts
Wraps defaultedOptions.queryFn (when not restoring) to register/unregister pending-task callbacks for thenable returns; introduces updateState to handle ngZone.run updates, pending-task lifecycle driven by fetchStatus, conditional ngZone.onError emission and rethrow via shouldThrowError, updates resultFromSubscriberSignal, and drains pending-task callbacks during cleanup.
Tests and changeset
packages/angular-query-experimental/src/__tests__/inject-query.test.ts, packages/angular-query-experimental/src/__tests__/pending-tasks.test.ts, .changeset/angular-query-preaccess-whenstable.md
Adds a test that captures a query data signal before render and asserts fixture.whenStable() remains pending until the async query resolves; adds a test ensuring destroying a component with a never-resolving query still allows ApplicationRef.whenStable() to resolve; includes a changeset documenting the patch.

QueryClient.resetQueries: restrict refetch set

Layer / File(s) Summary
Capture matched queries and refetch by predicate
packages/query-core/src/queryClient.ts, packages/query-core/src/__tests__/queryClient.test.tsx
resetQueries now finds matched queries up front, builds a queryHash set from them, resets each matched query, and calls refetchQueries with a predicate that only refetches queries whose queryHash is in that set; tests validate predicate-based resets refetch the expected queries.

Sequence Diagram(s)

sequenceDiagram
  participant Component as AngularComponent
  participant QueryFn as defaultedOptions.queryFn (wrapper)
  participant Pending as PendingTaskRegistry
  participant Observer as QueryObserver
  participant UpdateState as updateState
  participant Zone as ngZone
  participant Signal as resultFromSubscriberSignal

  Component->>QueryFn: invoke queryFn (may return thenable)
  QueryFn->>Pending: register pending task callback for thenable
  Observer->>UpdateState: emits new result (next/error)
  UpdateState->>Zone: run updates inside ngZone.run
  Zone->>Pending: complete/unregister pending task based on fetchStatus
  UpdateState->>Signal: update resultFromSubscriberSignal with latest result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • chughgaurav
  • TkDodo

Poem

I’m a rabbit in the zone, tapping my paw,
Waiting for queries to finish what they saw.
Pending tasks hold tight until results are clear,
WhenStable waits — no surprises here.
Hooray — soft hops and tests pass near. 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(angular-query): track pre-render query promises' directly and clearly describes the main technical change—registering pending tasks for query promises before render, which is the core fix for issue #10046.
Description check ✅ Passed The PR description comprehensively covers the changes (pending task registration, synchronous function handling, regression test), references the linked issue, details validation steps, and acknowledges local environment issues—exceeding the basic template requirements.
Linked Issues check ✅ Passed All coding objectives from issue #10046 are addressed: pending tasks registered for promise-returning query functions [#10046], synchronous functions unaffected [#10046], regression test added [#10046], and Angular test harness visibility [#10046]. Additionally, the query-core fix ensures predicate-based resets work correctly.
Out of Scope Changes check ✅ Passed All changes directly address issue #10046: angular-query changes fix the whenStable() visibility issue, the new test validates the regression, and the query-core change supports the reset predicate use case—no unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/angular-query-experimental/src/create-base-query.ts`:
- Around line 70-75: The pendingTasks.add() ref created for thenable results in
create-base-query.ts can be leaked if the thenable never settles; modify the
thenable handling around result.then(...) to ensure the pendingTaskRef is
released exactly once on cancellation/destruction: if an AbortSignal is present
in the query context, register a one-time abort listener that calls
pendingTaskRef() and removes itself; otherwise hook into the query
cancellation/cleanup path (the same place that cancels the request) to call
pendingTaskRef(); ensure both the result.then fulfillment/rejection handlers and
the cancellation listener invoke pendingTaskRef() idempotently (guarded so it
only runs once) and that any registered listener is removed after release.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5cca70e1-f9cd-4f4f-8a96-a4451e588fd6

📥 Commits

Reviewing files that changed from the base of the PR and between 63b3a72 and 79a8022.

📒 Files selected for processing (3)
  • .changeset/angular-query-preaccess-whenstable.md
  • packages/angular-query-experimental/src/__tests__/inject-query.test.ts
  • packages/angular-query-experimental/src/create-base-query.ts

Comment thread packages/angular-query-experimental/src/create-base-query.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Weird bug with Angular unit tests

1 participant